﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace laohan.Common.MQ.RabbitMQ
{
    /// <summary>
    /// 
    /// </summary>
    public class RabbitMQRunner
    {
        /// <summary>
        /// 
        /// </summary>
        public ConnectionFactory factory { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public IConnection connection { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string HostName { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string Password { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public int Port { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public RabbitMQRunner()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="hostName"></param>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="port"></param>
        public void InitParameter(string hostName, string userName, string password, int port)
        {
            this.HostName = hostName;
            this.UserName = userName;
            this.Password = password;
            this.Port = port;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Init(string clientProvidedName)
        {
            try
            {
                this.factory = new ConnectionFactory();

                factory.HostName = this.HostName;//RabbitMQ服务在本地运行
                factory.UserName = this.UserName;//用户名
                factory.Password = this.Password;//密码
                factory.Port = this.Port;

                this.connection = factory.CreateConnection(clientProvidedName);
            }
            catch (Exception ex)
            {
                throw new Exception("初始化RabbitMQ消息队列发生错误，错误原因：" + ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="queue"></param>
        /// <param name="msg">传递的消息内容</param>
        public void SendMsg(string queue, string msg)
        {
            try
            {
                if (this.connection == null)
                {
                    return;
                }

                using (var channel = this.connection.CreateModel())
                {
                    channel.QueueDeclare(queue, false, false, false, null);//创建一个名称为hello的消息队列

                    var body = Encoding.UTF8.GetBytes(msg);

                    string routingKey = queue;

                    channel.BasicPublish("", routingKey, null, body); //开始传递
                }
            }
            catch (Exception ex)
            {

                throw new Exception("发送消息发生错误，错误原因：" + ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="exchange"></param>
        /// <param name="msg"></param>
        public void SendMsgExchangeFanout(string exchange, string msg)
        {
            try
            {
                if (this.connection == null)
                {
                    return;
                }

                using (var channel = this.connection?.CreateModel())
                {
                    channel.ExchangeDeclare(exchange, "fanout");

                    var body = Encoding.UTF8.GetBytes(msg);

                    channel.BasicPublish(exchange, "", null, body); //开始传递
                }
            }
            catch (Exception ex)
            {

                throw new Exception("发送消息发生错误，错误原因：" + ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="queue"></param>
        public void ReceiveMsg(string queue, Action<string> action)
        {
            try
            {
                if (this.connection == null)
                {

                    return;
                }

                var channel = this.connection.CreateModel();

                channel.QueueDeclare(queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: null);

                var consumer = new EventingBasicConsumer(channel);

                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body.ToArray();
                    var message = Encoding.UTF8.GetString(body);

                    action?.Invoke(message);
                };

                channel.BasicConsume(queue, true, consumer);
            }
            catch (Exception ex)
            {

                throw new Exception("接收消息发生错误，错误原因：" + ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="queue"></param>
        public void ReceiveMsgExchangeFanout(string exchange, Action<string> action)
        {
            try
            {
                if (this.connection == null)
                {

                    return;
                }

                var channel = this.connection.CreateModel();

                channel.ExchangeDeclare(exchange: exchange, type: "fanout");

                var queueName = channel.QueueDeclare().QueueName;//声明一个队列，这个队列的名称随机

                channel.QueueBind(queue: queueName, exchange: exchange, routingKey: "");//将这个队列绑定（bind）到交换机上面

                var consumer = new EventingBasicConsumer(channel);

                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body.ToArray();
                    var message = Encoding.UTF8.GetString(body);

                    action?.Invoke(message);
                };

                channel.BasicConsume(queueName, true, consumer);
            }
            catch (Exception ex)
            {

                throw new Exception("接收消息发生错误，错误原因：" + ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Close()
        {
            try
            {
                if (this.connection != null)
                {
                    this.connection.Close();
                    this.connection.Dispose();

                    this.factory = null;
                }
            }
            catch (Exception ex)
            {

                throw new Exception("关闭RabbitMQ服务发生错误，错误原因：" + ex.Message);
            }
        }
    }
}
